#ifndef _LIBSVM_H
#define _LIBSVM_H

#define LIBSVM_VERSION 312

#ifdef __cplusplus
extern "C" {
#endif

  extern int libsvm_version;
  // 数据节点 一个样本矢量中的某个索引下的值
  // value=0的节点不存储，故需要index=-1来标识一个样本矢量的结束
  struct svm_node
  {
    int index; // 样本矢量的索引
    double value; // 该样本矢量下index的特征值
  };
  // 数据集，存放所有样本矢量的数据结构
  struct svm_problem
  {
    int l; // 样本的数量
    double *y; // 样本的标签
    struct svm_node **x; // 样本的
  };

  enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR };	/* svm_type */
  enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED }; /* kernel_type */

  struct svm_parameter
  {
    int svm_type; // svm的类型
    int kernel_type; // 核函数的类型
    int degree;	/* for poly */
    double gamma;	/* for poly/rbf/sigmoid */
    double coef0;	/* for poly/sigmoid */

    /* these are for training only */
    double cache_size; /* in MB */
    double eps;	/* stopping criteria */
    double C;	/* for C_SVC, EPSILON_SVR and NU_SVR */
    int nr_weight;		/* for C_SVC */
    int *weight_label;	/* for C_SVC */
    double* weight;		/* for C_SVC */
    double nu;	/* for NU_SVC, ONE_CLASS, and NU_SVR */
    double p;	/* for EPSILON_SVR */
    int shrinking;	/* use the shrinking heuristics */
    int probability; /* do probability estimates */
  };

  //
  // svm_model
  // 
  struct svm_model
  {
    struct svm_parameter param;	/* parameter */
    int nr_class;		/* number of classes, = 2 in regression/one class svm */ // 类别数
    int l;			/* total #SV */ // 支持向量的数量
    struct svm_node **SV;		/* SVs (SV[l]) */ 
    // 保存支持向量的指针，至于支持向量的内容，如果从文件中读取，内容会额外保留；如果是直接训练得来，则保留在原来的训练集中。如果训练完成后需要预报，原来的训练集内存不能释放。
    double **sv_coef;	/* coefficients for SVs in decision functions (sv_coef[k-1][l]) */ // 判别函数中的alpha
    double *rho;		/* constants in decision functions (rho[k*(k-1)/2]) */ // 判别函数总的b
    double *probA;		/* pariwise probability information */ 
    double *probB;

    /* for classification only */

    int *label;		/* label of each class (label[k]) */
    int *nSV;		/* number of SVs for each class (nSV[k]) */
    /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
    /* XXX */
    int free_sv;		/* 1 if svm_model is created by svm_load_model*/
				/* 0 if svm_model is created by svm_train */
  };
  // 训练函数
  struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
  // 用svm做交叉验证
  void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);
  
  // 保存训练好的模型到文件
  int svm_save_model(const char *model_file_name, const struct svm_model *model);
  // 从文件中加载模型到内存中
  struct svm_model *svm_load_model(const char *model_file_name);
  
  // 得到svm的类型
  int svm_get_svm_type(const struct svm_model *model);
  // 得到数据集的类别数
  int svm_get_nr_class(const struct svm_model *model);
  // 得到数据集的类别标号
  void svm_get_labels(const struct svm_model *model, int *label);
  double svm_get_svr_probability(const struct svm_model *model);
  

  // 训练好的模型预报样本的值
  double svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);
  double svm_predict(const struct svm_model *model, const struct svm_node *x);
  double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);

  void svm_free_model_content(struct svm_model *model_ptr);
  void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);
  void svm_destroy_param(struct svm_parameter *param);

  const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
  int svm_check_probability_model(const struct svm_model *model);

  void svm_set_print_string_function(void (*print_func)(const char *));

#ifdef __cplusplus
}
#endif

#endif /* _LIBSVM_H */
